/*
 *
 *  * Copyright (C) 2021 Huawei Device Co., Ltd.
 *  * Licensed under the Apache License, Version 2.0 (the "License");
 *  * you may not use this file except in compliance with the License.
 *  * You may obtain a copy of the License at
 *  *
 *  *     http://www.apache.org/licenses/LICENSE-2.0
 *  *
 *  * Unless required by applicable law or agreed to in writing, software
 *  * distributed under the License is distributed on an "AS IS" BASIS,
 *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  * See the License for the specific language governing permissions and
 *  * limitations under the License.
 *  *
 *
 */

package com.xuexiang.xui_lib.component.textview.marqueen;

import ohos.agp.components.AttrHelper;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.Path;
import ohos.agp.text.Font;
import ohos.agp.utils.Color;
import ohos.agp.utils.Rect;
import ohos.app.Context;

/**
 * 标签控件工具类
 *
 * @since 2021-04-10
 */
public class LabelViewHelper {
    private static final int LEFT_TOP = 1;
    private static final int RIGHT_TOP = 2;
    private static final int LEFT_BOTTOM = 3;
    private static final int RIGHT_BOTTOM = 4;
    private static final int DEFAULT_DISTANCE = 40;
    private static final int DEFAULT_HEIGHT = 20;
    private static final float OFFSET_RATIO = 1.0142135f;
    private static final float MIDDLE_RATIO = 1.5f;
    private static final float TWO = 2f;
    private static final int FIVE = 4;
    private static final int TEN = 11;

    /**
     * 默认边框颜色为透明
     */
    private static final int DEFAULT_STROKE_COLOR = 0x00000000;
    private static final int DEFAULT_STROKE_WIDTH = 1;
    private static final int DEFAULT_TEXT_SIZE = 14;
    private static final int DEFAULT_BACKGROUND_COLOR = 0x9F27CDC0;
    private static final int DEFAULT_TEXT_COLOR = 0xFFFFFFFF;
    private static final int DEFAULT_ORIENTATION = LEFT_TOP;
    private static final int DEFAULT_TEXT_STYLE = 0;

    private Context context;
    private int mAlpha;

    private int mDistance;
    private int mHeight;
    private int mBackgroundColor = DEFAULT_BACKGROUND_COLOR;

    private int mStrokeWidth;
    private int mStrokeColor = DEFAULT_STROKE_COLOR;

    private String mText = "";
    private int mTextSize;
    private int mTextStyle = DEFAULT_TEXT_STYLE;
    private String mTextFont = "";
    private int mTextColor = DEFAULT_TEXT_COLOR;

    private boolean isVisual = true;
    private int mOrientation = DEFAULT_ORIENTATION;

    private Paint mRectPaint;
    private Paint mRectStrokePaint;
    private Path mRectPath;
    private Path mTextPath;
    private Paint mTextPaint;
    private Rect mTextBound;

    /**
     * 构造方法
     *
     * @param callContext 上下文
     * @param attrs 属性集
     */
    public LabelViewHelper(Context callContext, AttrSet attrs) {
        context = callContext;
        initAttrs(context, attrs);
        initPaints();
    }

    /**
     * 初始化属性
     *
     * @param callContext 上下文
     * @param attrSet 属性集
     */
    private void initAttrs(Context callContext, AttrSet attrSet) {
        if (attrSet != null) {
            mDistance = px2vp(DEFAULT_DISTANCE);
            if (attrSet.getAttr("label_distance").isPresent()) {
                mDistance = attrSet.getAttr("label_distance").get().getDimensionValue();
            }
            mHeight = px2vp(DEFAULT_HEIGHT);
            if (attrSet.getAttr("label_height").isPresent()) {
                mHeight = attrSet.getAttr("label_height").get().getDimensionValue();
            }

            if (attrSet.getAttr("label_backgroundColor").isPresent()) {
                mBackgroundColor = attrSet.getAttr("label_backgroundColor").get().getColorValue().getValue();
            }

            mStrokeWidth = px2vp(DEFAULT_STROKE_WIDTH);
            if (attrSet.getAttr("label_strokeWidth").isPresent()) {
                mStrokeWidth = attrSet.getAttr("label_strokeWidth").get().getDimensionValue();
            }
            if (attrSet.getAttr("label_strokeColor").isPresent()) {
                mStrokeColor = attrSet.getAttr("label_strokeColor").get().getColorValue().getValue();
            }

            if (attrSet.getAttr("label_text").isPresent()) {
                mText = attrSet.getAttr("label_text").get().getStringValue();
            }

            if (attrSet.getAttr("label_textSize").isPresent()) {
                mTextSize = attrSet.getAttr("label_textSize").get().getDimensionValue();
            } else {
                mTextSize = px2vp(DEFAULT_TEXT_SIZE);
            }

            if (attrSet.getAttr("label_textStyle").isPresent()) {
                mTextStyle = attrSet.getAttr("label_textStyle").get().getIntegerValue();
            }

            if (attrSet.getAttr("label_textFont").isPresent()) {
                mTextFont = attrSet.getAttr("label_textFont").get().getStringValue();
            }

            if (attrSet.getAttr("label_textColor").isPresent()) {
                mTextColor = attrSet.getAttr("label_textColor").get().getColorValue().getValue();
            }

            if (attrSet.getAttr("label_visual").isPresent()) {
                isVisual = attrSet.getAttr("label_visual").get().getBoolValue();
            }

            if (attrSet.getAttr("label_orientation").isPresent()) {
                mOrientation = attrSet.getAttr("label_orientation").get().getIntegerValue();
            }
        }
    }

    private void initPaints() {
        mRectPaint = new Paint();
        mRectPaint.setDither(true);
        mRectPaint.setAntiAlias(true);
        mRectPaint.setStyle(Paint.Style.FILL_STYLE);

        mRectStrokePaint = new Paint();
        mRectStrokePaint.setDither(true);
        mRectStrokePaint.setAntiAlias(true);
        mRectStrokePaint.setStyle(Paint.Style.STROKE_STYLE);

        mRectPath = new Path();
        mRectPath.reset();

        mTextPath = new Path();
        mTextPath.reset();

        mTextPaint = new Paint();
        mTextPaint.setDither(true);
        mTextPaint.setAntiAlias(true);
        mTextPaint.setStrokeJoin(Paint.Join.ROUND_JOIN);
        mTextPaint.setStrokeCap(Paint.StrokeCap.SQUARE_CAP);

        mTextBound = new Rect();
    }

    /**
     * 绘制方法
     *
     * @param canvas 画布对象
     * @param measuredWidth 宽
     * @param measuredHeight 高
     */
    public void onDraw(Canvas canvas, int measuredWidth, int measuredHeight) {
        if (!isVisual || mText == null) {
            return;
        }

        float actualDistance = mDistance + mHeight / TWO;
        calcOffset(measuredWidth, measuredHeight);

        float beginWidthOffett = (OFFSET_RATIO * actualDistance) / TWO - mTextBound.getWidth() / TWO;
        if (beginWidthOffett < 0) {
            beginWidthOffett = 0;
        }

        mRectPaint.setColor(new Color(mBackgroundColor));
        if (mAlpha != 0) {
            mRectPaint.setAlpha(mAlpha);
        }

        mRectStrokePaint.setColor(new Color(mStrokeColor));
        mRectStrokePaint.setStrokeWidth(mStrokeWidth);

        canvas.drawPath(mRectPath, mRectPaint);
        canvas.drawPath(mRectPath, mRectStrokePaint);

        mTextPaint.setTextSize(mTextSize);
        mTextPaint.setColor(new Color(mTextColor));
        mTextPaint.getTextBounds(mText);
        mTextPaint.setFont(Font.DEFAULT);

        canvas.drawTextOnPath(mTextPaint, mText, mTextPath, beginWidthOffett, mTextBound.getHeight() / TWO);
    }

    /**
     * 计算偏移量
     *
     * @param measuredWidth
     * @param measuredHeight
     */
    private void calcOffset(int measuredWidth, int measuredHeight) {
        float startPosX = measuredWidth - mDistance - mHeight;
        float endPosX = measuredWidth;
        float startPosY = measuredHeight - mDistance - mHeight;
        float endPosY = measuredHeight;
        float middle = mHeight / MIDDLE_RATIO;

        switch (mOrientation) {
            case LEFT_TOP: // LEFT_TOP
                mRectPath.reset();
                mRectPath.moveTo(0, mDistance);
                mRectPath.lineTo(mDistance, 0);
                mRectPath.lineTo(mDistance + mHeight, 0);
                mRectPath.lineTo(0, mDistance + mHeight);
                mRectPath.close();

                mTextPath.reset();
                mTextPath.moveTo(0, mDistance + middle);
                mTextPath.lineTo(mDistance + middle, 0);
                mTextPath.close();
                break;
            case RIGHT_TOP: // RIGHT_TOP
                mRectPath.reset();
                mRectPath.moveTo(startPosX, 0);
                mRectPath.lineTo(startPosX + mHeight, 0);
                mRectPath.lineTo(endPosX, mDistance);
                mRectPath.lineTo(endPosX, mDistance + mHeight);
                mRectPath.close();

                mTextPath.reset();
                mTextPath.moveTo(startPosX + middle - TEN, 0);
                mTextPath.lineTo(endPosX, mDistance + middle - FIVE);
                mTextPath.close();

                break;
            case LEFT_BOTTOM: // LEFT_BOTTOM
                mRectPath.reset();
                mRectPath.moveTo(0, startPosY);
                mRectPath.lineTo(mDistance + mHeight, endPosY);
                mRectPath.lineTo(mDistance, endPosY);
                mRectPath.lineTo(0, startPosY + mHeight);
                mRectPath.close();

                mTextPath.reset();
                mTextPath.moveTo(0, startPosY + middle);
                mTextPath.lineTo(mDistance + middle - TEN, endPosY);
                mTextPath.close();
                break;
            case RIGHT_BOTTOM: // RIGHT_BOTTOM
                mRectPath.reset();
                mRectPath.moveTo(startPosX, endPosY);
                mRectPath.lineTo(measuredWidth, startPosY);
                mRectPath.lineTo(measuredWidth, startPosY + mHeight);
                mRectPath.lineTo(startPosX + mHeight, endPosY);
                mRectPath.close();

                mTextPath.reset();
                mTextPath.moveTo(startPosX + middle, endPosY);
                mTextPath.lineTo(endPosX, startPosY + middle);
                mTextPath.close();
                break;
            default:
                break;
        }
    }

    private int px2vp(float px) {
        return AttrHelper.vp2px(px, context);
    }

    /**
     * 设置label高
     *
     * @param view 视图（设置的对象）
     * @param height 高度值
     */
    public void setLabelHeight(Component view, int height) {
        if (mHeight != px2vp(height)) {
            mHeight = px2vp(height);
            view.invalidate();
        }
    }

    /**
     * 获取label高度
     *
     * @return 返回label的测量高度值
     */
    public int getLabelHeight() {
        return px2vp(mHeight);
    }

    /**
     * 获取label宽
     *
     * @return 返回label宽
     */
    public int getLabelStrokeWidth() {
        return px2vp(mStrokeWidth);
    }

    /**
     * 设置label宽
     *
     * @param view 设置的对象
     * @param strokeWidth 宽度值
     */
    public void setLabelStrokeWidth(Component view, int strokeWidth) {
        if (mStrokeWidth != px2vp(strokeWidth)) {
            mStrokeWidth = px2vp(strokeWidth);
            view.invalidate();
        }
    }

    /**
     * 获取label距离
     *
     * @return 返回距离
     */
    public int getLabelDistance() {
        return px2vp(mDistance);
    }

    /**
     * 设置label距离
     *
     * @param view 设置的对象
     * @param distance 宽度值
     */
    public void setLabelDistance(Component view, int distance) {
        if (mDistance != px2vp(distance)) {
            mDistance = px2vp(distance);
            view.invalidate();
        }
    }

    /**
     * 获取label是否可见标记
     *
     * @return 返回是否可见标记
     */
    public boolean isLabelVisual() {
        return isVisual;
    }

    /**
     * 设置label是否可见标记
     *
     * @param view 设置是否可见的对象
     * @param isCallVisual 是否可见标记
     */
    public void setLabelVisual(Component view, boolean isCallVisual) {
        if (isVisual != isCallVisual) {
            isVisual = isCallVisual;
            view.invalidate();
        }
    }

    /**
     * 获取label方向
     *
     * @return 返回label方向值
     */
    public int getLabelOrientation() {
        return mOrientation;
    }

    /**
     * 设置label方向
     *
     * @param view 设置的对象
     * @param orientation 方向值
     */
    public void setLabelOrientation(Component view, int orientation) {
        if (mOrientation != orientation && orientation <= RIGHT_BOTTOM && orientation >= LEFT_TOP) {
            mOrientation = orientation;
            view.invalidate();
        }
    }

    /**
     * 获取labelText颜色
     *
     * @return 返回颜色值
     */
    public int getLabelTextColor() {
        return mTextColor;
    }

    /**
     * 设置labelText颜色
     *
     * @param view 设置对象
     * @param textColor 颜色值
     */
    public void setLabelTextColor(Component view, int textColor) {
        if (mTextColor != textColor) {
            mTextColor = textColor;
            view.invalidate();
        }
    }

    /**
     * 获取label背景颜色
     *
     * @return 返回颜色值
     */
    public int getLabelBackgroundColor() {
        return mBackgroundColor;
    }

    /**
     * 设置label背景颜色
     *
     * @param view 设置对象
     * @param backgroundColor 颜色值
     */
    public void setLabelBackgroundColor(Component view, int backgroundColor) {
        if (mBackgroundColor != backgroundColor) {
            mBackgroundColor = backgroundColor;
            view.invalidate();
        }
    }

    /**
     * 获取label点击颜色
     *
     * @return 返回颜色值
     */
    public int getLabelStrokeColor() {
        return mStrokeColor;
    }

    /**
     * 设置label触摸颜色
     *
     * @param view 设置对象
     * @param strokeColor 颜色值
     */
    public void setLabelStrokeColor(Component view, int strokeColor) {
        if (mStrokeColor != strokeColor) {
            mStrokeColor = strokeColor;
            view.invalidate();
        }
    }

    /**
     * 设置label背景透明毒液
     *
     * @param view 设置对象
     * @param alpha 透明值
     */
    public void setLabelBackgroundAlpha(Component view, int alpha) {
        if (mAlpha != alpha) {
            mAlpha = alpha;
            view.invalidate();
        }
    }

    /**
     * 获取labelText
     *
     * @return 返回text
     */
    public String getLabelText() {
        return mText;
    }

    /**
     * 设置labeltext内容
     *
     * @param view 设置对象
     * @param text 内容
     */
    public void setLabelText(Component view, String text) {
        if (mText == null || !mText.equals(text)) {
            mText = text;
            view.invalidate();
        }
    }

    /**
     * 获取labelText 大小
     *
     * @return 返回text 大小
     */
    public int getLabelTextSize() {
        return px2vp(mTextSize);
    }

    /**
     * 设置labeltext字体大下
     *
     * @param view 设置对象
     * @param textSize 字体大小
     */
    public void setLabelTextSize(Component view, int textSize) {
        if (mTextSize != textSize) {
            mTextSize = textSize;
            view.invalidate();
        }
    }

    /**
     * 获取labelText style
     *
     * @return 返回text style值
     */
    public int getLabelTextStyle() {
        return mTextStyle;
    }

    /**
     * 设置labeltext style值
     *
     * @param view 设置对象
     * @param textStyle style值
     */
    public void setLabelTextStyle(Component view, int textStyle) {
        if (mTextStyle == textStyle) {
            return;
        }
        mTextStyle = textStyle;
        view.invalidate();
    }

    /**
     * 设置labeltext字体
     *
     * @param view 设置对象
     * @param textFont 字体
     */
    public void setLabelTextFont(Component view, String textFont) {
        mTextFont = textFont;
        view.invalidate();
    }

    /**
     * 获取labelText 字体
     *
     * @return 返回text 字体值
     */
    public String getLabelTextFont() {
        return mTextFont;
    }
}
